﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="NetworkMonitor.cs" company="XamlNinja">
//   2011 Richard Griffin and Ollie Riches
// </copyright>
// <summary>
//   The network monitor.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace dIRca.Extras
{
    using System;
    using Microsoft.Phone.Net.NetworkInformation;
    using Microsoft.Phone.Reactive;

    /// <summary>
    /// The network monitor, uses reactive extensions to publish the current network monitor.
    /// </summary>
    public sealed class NetworkMonitor : INetworkService, IDisposable
    {
        /// <summary>
        /// The status subject.
        /// </summary>
        private BehaviorSubject<bool> statusSubject = new BehaviorSubject<bool>(DetermineCurrentStatusImpl());

        /// <summary>
        /// The network observer.
        /// </summary>
        private IDisposable networkObserver;

        /// <summary>
        /// Initializes a new instance of the <see cref="NetworkMonitor"/> class.
        /// </summary>
        /// <param name="frequency">
        /// The frequency to check the network connection.
        /// </param>
        public NetworkMonitor(int frequency)
        {
            this.networkObserver = Observable.Interval(TimeSpan.FromMilliseconds(frequency))
                        .Select(DetermineCurrentStatus)
                        .Subscribe(this.statusSubject);
        }

        /// <summary>
        /// The dispose
        /// </summary>
        public void Dispose()
        {
            if (this.networkObserver != null)
            {
                this.networkObserver.Dispose();
                this.networkObserver = null;
            }

            if (this.statusSubject != null)
            {
                this.statusSubject.OnCompleted();
                this.statusSubject = null;
            }
        }

        /// <summary>
        /// Returns the current status as an observable instance, any future changes will automatically notify subscribers
        /// to the observable.
        /// </summary>
        /// <returns>
        /// Returns an observable status.
        /// </returns>
        public IObservable<bool> Status()
        {
            return this.statusSubject.DistinctUntilChanged();
        }

        /// <summary>
        /// The determine current status.
        /// </summary>
        /// <param name="interval">
        /// The interval.
        /// </param>
        /// <returns>
        /// Returns the current network type.
        /// </returns>
        private static bool DetermineCurrentStatus(long interval)
        {
            return DetermineCurrentStatusImpl();
        }

        /// <summary>
        /// The determine current status impl.
        /// </summary>
        /// <returns>
        /// Returns the current network type.
        /// </returns>
        private static bool DetermineCurrentStatusImpl()
        {
            var currentNetworkType = NetworkInterface.NetworkInterfaceType;
            switch (currentNetworkType)
            {
                case NetworkInterfaceType.MobileBroadbandCdma:
                    return true;
                case NetworkInterfaceType.MobileBroadbandGsm:
                    return true;
                case NetworkInterfaceType.Wireless80211:
                    return true;
                case NetworkInterfaceType.Ethernet:
                    return true;
                default:
                    return false;
            }
        }
    }
}